
package view;

import controllers.SyntacticValidator;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.Random;
import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Task;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.TextArea;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;

/**
 * @version 1.0
 * @date 13/04/2012
 * @author john
 */
public class ProgressPane extends GridPane{
    
    private long totalLinesNumber;
    private String filePath;
    
    private final double minControlsWidth=400;
    private final double minTextAHeight=200;
    private final DoubleProperty controlsWidthProperty;
    private final DoubleProperty stateTAHeightProperty;
    
    private final Label fileIDL;
    private final Label fileIDL2;
    private final Label percentageL;
    private final ProgressBar progressBar;
    private final TextArea stateTA;
    
    private final Application application;

    public ProgressPane(final Scene mainScene, Application application, String filePath, long totalLinesNumber) {
        this.application=application;
        this.filePath=filePath;
        this.totalLinesNumber=totalLinesNumber;
        setId("progress-bar");
        setPadding(new Insets(25, 40, 20, 40));
        setVgap(10);
        controlsWidthProperty=new SimpleDoubleProperty();
        controlsWidthProperty.bind(mainScene.widthProperty().subtract(this.getPadding().getLeft()).subtract(this.getPadding().getRight()));
        stateTAHeightProperty=new SimpleDoubleProperty();
        stateTAHeightProperty.bind(mainScene.heightProperty().subtract(this.getPadding().getTop()).subtract(this.getPadding().getBottom()).subtract(110));
        HBox fileIDHBox=new HBox(7);
        fileIDL=new Label("Nombre del archivo:");
        fileIDL2=new Label(String.valueOf(String.valueOf(filePath)));
        fileIDHBox.getChildren().setAll(fileIDL,fileIDL2);
        percentageL=new Label("Líneas Procesadas / Líneas Totales");
        GridPane.setHalignment(percentageL, HPos.CENTER);
        progressBar=new ProgressBar(0);
        progressBar.setMinWidth(minControlsWidth);
        progressBar.prefWidthProperty().bind(controlsWidthProperty);
        stateTA=new TextArea();
        stateTA.setMinHeight(minTextAHeight);
        stateTA.setEditable(false);
        stateTA.prefWidthProperty().bind(controlsWidthProperty);
        stateTA.prefHeightProperty().bind(stateTAHeightProperty);
        add(fileIDHBox, 0, 0);
        add(percentageL, 0, 1);
        add(progressBar, 0, 2);
        add(stateTA, 0, 3);
    }
    
    /**
     * Inicializa el thread de consulta y relaciona su progreso con los
     * elementos graficos que informan al usuario del avance.
     * @param fileAnalysisTask 
     */
    protected Task createTask(){
        Task fileAnalysisTask=checkProgress();
        progressBar.progressProperty().unbind();
        progressBar.setProgress(0);
        progressBar.progressProperty().bind(fileAnalysisTask.progressProperty());
        //stateTA.textProperty().bind(fileAnalysisTask.messageProperty());
        fileAnalysisTask.progressProperty().addListener(
            new ChangeListener<Number>() {
                @Override
                public void changed(ObservableValue<? extends Number> arg0, Number oldLinesNumber, Number newLinesNumber) {
                    percentageL.setText(((int)(newLinesNumber.doubleValue()*totalLinesNumber))+" / "+totalLinesNumber);
                    if(newLinesNumber.intValue()==1){
                        ((MainWindow)application).endFileAnalysis();
                        stateTA.textProperty().unbind();
                        stateTA.requestFocus();
                        stateTA.selectAll();
                        stateTA.copy();
                        stateTA.deselect();
                    }
                }
            }
        );
        fileAnalysisTask.messageProperty().addListener(
            new ChangeListener<String>() {
                @Override
                public void changed(ObservableValue<? extends String> arg0, String oldMessage, String newMessage) {
                    stateTA.appendText(newMessage+"\n");
                }
            }
        );
        return fileAnalysisTask;
    }
    
    /**
     * Inicializa el thread de consulta a la base de datos para conocer el estado
     * de la revisi√≥n del archivo
     * @return Task: una tarea que consulta constantemente el estado de analisis 
     * de un archivo
     */
    private Task checkProgress(){
        return new Task(){
            @Override
            protected Object call() throws Exception {
                try {
                    SyntacticValidator validator = new SyntacticValidator();
                    FileInputStream fstream = new FileInputStream(filePath);
                    // Get the object of DataInputStream
                    DataInputStream in = new DataInputStream(fstream);
                    BufferedReader br = new BufferedReader(new InputStreamReader(in));
                    String strLine;
                    //Read File Line By Line
                    int correct = 0;
                    int wrong = 0;
                    long startTime = System.nanoTime();
                    int count = 0;
                    while ((strLine = br.readLine()) != null) {
                        count++;
                        // Print the content on the console
                        //System.out.print(" Nice! ");
                        if (validator.validate(strLine)) {
                            correct++;
                            //System.out.print(" Nice! ");
                            //updateMessage(getMessage()+"\nLínea "+count+" Nice! ");
                            updateMessage("Línea "+count+" Nice! ");
                        } else {
                            wrong++;
                            //System.out.print(" Wrong ");
                            //updateMessage(getMessage()+"\nLínea "+count+" WRONG ");
                            updateMessage("Línea "+count+" WRONG! ");
                        }
                        updateProgress(count,totalLinesNumber);
                        waitSomeTime();
                        //System.out.println(strLine);
                    }
                    
                    System.out.println("Good ones: " + correct);
                    System.out.println("Spoilt ones: " + wrong);
                    System.out.println("Total:  " + (wrong + correct));
                    long estimatedTime = System.nanoTime() - startTime;
                    System.out.println("Time:  " + ((float) estimatedTime / (float) 1000000000) + " segundos");
                    //Close the input stream
                    in.close();
                } catch (Exception e) {//Catch exception if any
                    System.err.println("Error: " + e.getMessage());
                }
                updateProgress(totalLinesNumber, totalLinesNumber);
                updateMessage("\nArchivo completado.");
                return true;
            }
        };
    }
    
    /**
     * Para darle tiempo al textarea y que se pueda actualizar
     * @throws InterruptedException 
     */
    public static void waitSomeTime() throws InterruptedException{
        Thread.sleep(new Random(System.currentTimeMillis()).nextInt(300));
    }
    
}
